class Tunnel {
  listeners = {}
  constructor(opts) {
    this.opts = opts;
    window.addEventListener('message', (e) => {
      const { signal, origin } = this.opts;
      if (e.origin !== origin || e.data.signal !== signal)
        return
      this.onRecv && this.onRecv(e.data.key, e.data.value)
      this.listeners[e.data.key] && this.listeners[e.data.key].map(v => v(e.data.value))
    })
  }
  send(key, value) {
    const { signal, origin, window } = this.opts;
    if (!key) return this;
    const msg = { signal, key, value }
    window.postMessage(msg, origin);
    return this;
  }
  recv(func) {
    this.onRecv = func
    return this;
  }
  on(key, func) {
    this.listeners[key] = this.listeners[key] || []
    this.listeners[key].push(func)
    return () => this.off(key, func)
  }

  off(key, func) {
    if (!this.listeners[key])
      return;
    this.listeners[key] = this.listeners[key].filter(v => v !== func)
  }
}